package com.css.common.core.utils;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;

import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.Date;

/**
 * @description: id生成工具类
 * @Title: IdUtil
 * @Author xlw
 * @Package com.invoice.tcc.util
 * @Date 2024/10/25 13:50
 */
public class IdUtils {

    private static String time;

    private static int shh = 0;///顺序号

//    public static void main (String[] d){
//        for(int i=0;i<100;i++){
//            System.out.println(createId(4,null));
//        }
//
//    }

    private static StringRedisTemplate redisTemplate;

    /**
     * id 前缀
     */
    private static final String ID_PREFIX = "ID_INCREASE:";

    /**
     * Redis 模板
     *
     * @return {@link StringRedisTemplate }
     */
    public static StringRedisTemplate redisTemplate() {
        if (redisTemplate == null) {
            redisTemplate = SpringIocUtils.getBean(StringRedisTemplate.class);
        }
        return redisTemplate;
    }

    /**
     * Redis 序列号
     *
     * @param key key
     * @return {@link String }
     */
    @NotNull
    public static String redisSerialNumber(String key, int len) {
        //脚本
        String jb = "--key\n" +
                "local idKey = KEYS[1]\n" +
                "local len = ARGV[1]\n" +
                "local formatStr = '%0' .. len .. 'd'\n" +
                "-- 过期时间\n" +
                "local timeout = 3;\n" +
                "if (redis.call('EXISTS', idKey) == 1) then\n" +
                "    -- 存在，加1\n" +
                "    redis.call('INCR', idKey)\n" +
                "    redis.call('expire', idKey, timeout)\n" +
                "else\n" +
                "    -- 不存在\n" +
                "    redis.call('set', idKey, 1)\n" +
                "    redis.call('expire', idKey, timeout)\n" +
                "end\n" +
                "local value = redis.call('get', idKey)\n" +
                "-- 补零\n" +
                "return string.format(formatStr, value)";
        //通过当前时间戳获取redis自增
        DefaultRedisScript script = new DefaultRedisScript();
        script.setResultType(String.class);
        script.setScriptText(jb);
        String serialNumber = (String) redisTemplate().execute(script, ListUtil.toList(ID_PREFIX + key), String.valueOf(len));
        return serialNumber;
    }

    /**
     * 创建付款id
     *
     * @return {@link String }
     */
    public static String createFkid() {
        StringBuilder id = new StringBuilder();
        String now = DateUtil.format(LocalDateTime.now(), "yyMMddHHmmssSSS");
        //分布式序号生成
        String s = redisSerialNumber("FK_ID:" + now, 4);
        id.append(now);
        id.append(s);
        return id.toString();
    }

    /**
     * 创建订单 ID, 一共28位
     * 固定4位+15位日期yyMMddHHmmssSSS+4位业务类型代码+5位随机数
     *
     * @return {@link String }
     */
    public static String createOrderId(String ywdm) {
        StringBuilder id = new StringBuilder();
        id.append("3AD7");
        String now = DateUtil.format(LocalDateTime.now(), "yyMMddHHmmssSSS");
        id.append(now);
        id.append(ywdm);
        //分布式序号生成
        String s = redisSerialNumber("ORDER_ID:" + now, 5);
        id.append(s);
        return id.toString();
    }

    public static String createNcpSeqId() {
        StringBuilder seqId = new StringBuilder();
        String now = DateUtil.format(LocalDateTime.now(), "yyyyMMddHHmmssSSS");
        //分布式序号生成
        String s = redisSerialNumber("NCP_SEQ_ID:" + now, 5);
        seqId
                .append(s)
                .append(RandomUtil.randomString(10))
                .append(now);
        return seqId.toString();
    }

    /**
     * 创建发票 UUID
     *
     * @return {@link String }
     */
    public static String createInvoiceUUID(String ywdm) {
        StringBuilder id = new StringBuilder();
        id.append("2FPKJ");
        id.append(StrUtil.isNotBlank(ywdm) ? ywdm : RandomUtil.randomNumbers(4));
        String now = DateUtil.format(LocalDateTime.now(), "yyMMddHHmmssSSS");
        id.append(now);
        //分布式序号生成
        String s = redisSerialNumber("INVOICE_UUID:" + now, 5);
        id.append(s);
        return id.toString();
    }

    /**
     * 创建受理流水号
     *
     * @param ywdm YWDM
     * @return {@link String }
     */
    public static String createSllsh(String ywdm) {
        StringBuilder id = new StringBuilder();
        id.append("8PCDD");
        id.append(StrUtil.isNotBlank(ywdm) ? ywdm : RandomUtil.randomNumbers(4));
        String now = DateUtil.format(LocalDateTime.now(), "yyMMddHHmmssSSS");
        id.append(now);
        //分布式序号生成
        String s = redisSerialNumber("SLLSH:" + now, 5);
        id.append(s);
        return id.toString();
    }

    public static String fphkUUID() {
        StringBuilder id = new StringBuilder();
        id.append("FPHK");
        String now = DateUtil.format(LocalDateTime.now(), "yyyyMMddHHmmssSSS");
        id.append(now);
        //分布式序号生成
        String s = redisSerialNumber("FPHK:" + now, 5);
        id.append(s);
        return id.toString();
    }

    public static String createUUID(String key,String ywdm) {
        StringBuilder id = new StringBuilder();
        id.append(key);
        id.append(StrUtil.isNotBlank(ywdm) ? ywdm : RandomUtil.randomNumbers(4));
        String now = DateUtil.format(LocalDateTime.now(), "yyyyMMddHHmmssSSS");
        id.append(now);
        //分布式序号生成
        String s = redisSerialNumber("FPHK:" + now, 5);
        id.append(s);
        return id.toString();
    }
}
